using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;

namespace ReportMaintenanceUtility
{
	public class DataSet : GenericBase<DataSet>
	{
		#region PRIVATE MEMBERS
		private DataSetType			_seed	= null;
		private string				_name	= string.Empty;
		private Query				_query	= null;
		private List<Field>			_fields = null;
		#endregion

		#region PUBLIC PROPERTIES

		/// <summary>
		/// The Dataset name
		/// </summary>
		public string Name
		{
			get { return this._name; }
			set
			{
				this.PrepStateChange("Name");
				//this.NotifyPropertyChanged("Name");
				this._name = value;
				//this._isDirty = true;
			}
		}

		/// <summary>
		/// Defines the properties of a query used by a dataset, such as CommandType, CommandText and QueryParameters
		/// </summary>
		public Query Query
		{
			get { return this._query; }
			set
			{
				this.PrepStateChange("Query");
				//this.NotifyPropertyChanged("Query");
				this._query = value;
				//this._isDirty = true;
			}
		}

		/// <summary>
		/// Describes the list of fields returned by the associated query...
		/// </summary>
		public List<Field> Fields
		{
			get { return this._fields; }
		}

		#endregion

		#region CONSTRUCTOR(S)

		private DataSet(DataSet ds)
		{
			if (ds == null)
			{
				throw new ArgumentNullException();
			}
			else
			{
				this._name = ds._name;
				this._seed = (DataSetType)ds.CreateSeedCopy();
				base.CopyListeners(ds);
				this.Initialize();
			}
		}

		public DataSet(DataSetType dst)
		{
			if (dst == null)
			{
				throw new ArgumentNullException();
			}
			else
			{
				this._name = dst.Name;
				this._seed = dst;
				this.Initialize();
			}
		}
		protected override void Initialize()
		{
			for (int i = 0; i < this._seed.Items.Length; i++)
			{
				if (this._seed.Items[i] is QueryType)
				{
					this._query = new Query((QueryType)this._seed.Items[i]);
					this._query.PropertyChanged += this.PropertyChangedListener;
				}
				else if (this._seed.Items[i] is FieldsType)
				{
					List<Field> list = new List<Field>();
					foreach (FieldType ft in ((FieldsType)this._seed.Items[i]).Field)
					{
						list.Add(new Field(ft));
					}
					this._fields = list;
				}
			}
		}
		#endregion

		#region INTERFACE IMPLEMENTATION(S)

		public override bool EqualTo(DataSet other)
		{
			if (other == null)
			{
				return false;
			}
			else if (!this._name.Equals(other._name, StringComparison.CurrentCultureIgnoreCase))
			{
				return false;
			}
			else
			{
				return CompareTo<Query>.Compare(this.Query, other.Query);
			}
		}
	
		public override List<ChangeLog> SaveState()
		{
			List<ChangeLog> log = new List<ChangeLog>();
			ChangeLog sub = null;

			if (this._isDirty)
			{
				if (this._name != this._copy.Name)
				{
					this._seed.Name = this._name;
					sub = new ChangeLog(ChangeType.DataSetName, this._copy._name, this._name);
					log.Add(sub);
				}
				if (!CompareTo<Query>.Compare(this._query, this._copy.Query))
				{
					sub = null;
					List<object> items = new List<object>(this._seed.Items);

					if (this._query == null && this._copy._query != null)
					{
						QueryType qt = null;
						sub = new ChangeLog(ChangeType.DataSetQueryDelete, this._copy._query, this._query);

						//deleted...
						foreach (object o in items)
						{
							if (o is QueryType)
							{
								qt = (QueryType)o;
								break;
							}
						}

						items.Remove(qt);
						this._seed.Items = items.ToArray();
					}
					else if (this._query != null && this._copy._query == null)
					{
						//added...
						sub = new ChangeLog(ChangeType.DataSetQueryAdd, this._copy._query, this._query);
						sub.RelatedChanges.AddRange(this._query.SaveState());
						items.Add(this._query.GetSeedObject());
						this._seed.Items = items.ToArray();
					}
					else
					{
						sub = new ChangeLog(ChangeType.DataSetQueryChange, this._copy._query, this._query);
						sub.RelatedChanges.AddRange(this._query.SaveState());
					}

					log.Add(sub);
				}
			}

			this.ClearState();
			return log;
		}

		public override void RestoreState()
		{
			if (this._copy != null)
			{
				this._name = ((DataSet)this)._copy.Name;
				this._query = ((DataSet)this)._copy.Query;
				this._fields = ((DataSet)this)._copy.Fields;
			}
			this.ClearState();
		}

		public override DataSet CreateDeepCopy()
		{
			if (this._copy != null)
			{
				return this._copy;
			}
			return new DataSet(this);
		}
		#endregion

		public override object CreateSeedCopy()
		{
			//create new root DataSetType seed object
			DataSetType dst = new DataSetType();
			dst.Name = this._seed.Name;

			//start a new list of objects...
			List<object> items = new List<object>();

			if (this._query != null)
			{
				items.Add(this._query.CreateSeedCopy());
			}

			if (this._fields != null)
			{
				FieldsType fts = new FieldsType();
				List<FieldType> fields = new List<FieldType>();

				foreach (Field f in this._fields)
				{
					fields.Add((FieldType)f.CreateSeedCopy());
				}
				fts.Field = fields.ToArray();
				items.Add(fts);
			}

			dst.Items = items.ToArray();
			return dst;
		}

		public DataSetType GetSeedObject()
		{
			return this._seed;
		}
	}
}
